package com.lsp.java.jdk8;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

/**
 * @Description
 * @Author lishengpeng
 * @Date 2022/4/28 15:58
 */
public class DateTimeOpe {
    public static void main(String[] args) throws ParseException {
        //LocalDate、LocalDateTime、LocalTime;
        //获取当前时间
        //获取当前时间  now()/now(ZoneId zone)
        LocalDate localDate = LocalDate.now();
        LocalTime localTime = LocalTime.now();
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(String.format("localDate:%s,localTime:%s,localDateTime:%s,", localDate, localTime,
                localDateTime));
        //设置指定的时间
        //of(): 设置指定的年、月、日、时、分、秒。没有偏移量
        LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 8, 1, 1, 1);
        //获取一天中小时间和最大时间
        LocalDate localDate1 = LocalDate.now();
        LocalDateTime min = LocalDateTime.of(localDate1, LocalTime.MIN);
        LocalDateTime max = LocalDateTime.of(localDate1, LocalTime.MAX);
        System.out.println(String.format("localDateTime1:%s,localDate2:%s,min:%s,max:%s", localDateTime1, localDate1,
                min, max));
        //获取年/月/日
        //getXxx()
        System.out.println("------------------------");
        System.out.println(localDateTime.getDayOfMonth());
        System.out.println(localDateTime.getDayOfWeek());    //枚举
        System.out.println(localDateTime.getMonth());        //枚举
        System.out.println(localDateTime.getMonthValue());
        System.out.println(localDateTime.getMinute());
        System.out.println("------------------------");
        //设置时间/日期(绝对值)
        //设置时间/日期  withDayOfMonth()/withDayOfYear()/withMonth()/withYear()
        LocalDate localDate2 = localDate.withDayOfMonth(5);  //设置为本月第5天
        System.out.println(String.format("localDate1:%s,localDate2:%s", localDate, localDate2));
        //设置偏移量
        LocalDateTime localDateTime3 = localDateTime.plusDays(3);
        LocalDateTime localDateTime4 = localDateTime.minusDays(10);
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate style = LocalDate.parse("2022-08-25", pattern).minusDays(7);
        String datestr = style.toString();
        System.out.println("格式化：" + datestr);
        System.out.println(String.format("localDateTime3:%s,localDateTime4:%s", localDateTime3, localDateTime4));
        /*****************************************Instant  时间线上的一个瞬时点，被用来记录应用程序中的事件时间戳。************************/
        //日期变更子午线时间
        Instant instant = Instant.now();
        System.out.println(String.format("instant:%s", instant));
        // 添加时间的偏移量--东八区时区
        OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
        System.out.println(String.format("offsetDateTime:%s", offsetDateTime));
        //获取时间戳(从1970年1月1日0时0分0秒开始的毫秒数)
        long l = instant.toEpochMilli();
        System.out.println(String.format("l:%s", l));
        //根据毫秒时间戳返回Instant对象
        Instant instant1 = Instant.ofEpochMilli(l);
        System.out.println(String.format("instant1:%s", instant1));
        /*************************DateTimeFormatter ofPattern********************************/
        //静态方法，返回一个指定字符串格式的DateTimeFormatter
        //format格式化为字符串
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String format = dateTimeFormatter.format(LocalDate.now());
        System.out.println(String.format("format:%s", format));
        //时间戳转为字符串
        DateTimeFormatter dateTimeFormatter6 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format6 = dateTimeFormatter6.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(l),
                ZoneId.systemDefault()));
        System.out.println(String.format("format6:%s", format6));
        //parse解析为时间/日期
        DateTimeFormatter dateTimeFormatter7 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime parse = LocalDateTime.parse("2021-07-03 05:33:30", dateTimeFormatter7);
        System.out.println(String.format("parse:%s", parse));
        //Period 用于计算日期相对间隔(无法隔月计算)
        //用于计算两个日期间隔
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate startDate = LocalDate.parse("2019-03-04", fmt);
        LocalDate endDate = LocalDate.parse("2018-02-01", fmt);
        Period period = Period.between(startDate, endDate);
        System.out.println(String.format("相差:%s年,%s个月,%s天", period.getYears(), period.getMonths(), period.getDays()));
        System.out.println(String.format("相差:%s天", startDate.toEpochDay() - endDate.toEpochDay()));
        //隔月计算要用toEpochDay方法
        //获取当前时间
        LocalDate localDate3 = localDate.plusDays(100);
        System.out.println(String.format("无法隔月:%s,隔月%s", Period.between(localDate1, localDate2).getDays(),
                localDate3.toEpochDay() - localDate.toEpochDay()));
        //Duration 用于计算时间间隔
        LocalDateTime localDateTime2 = localDateTime.plusDays(1);
        System.out.println(String.format("时间相差:%s", Duration.between(localDateTime, localDateTime2).getSeconds()));
        //计算日期绝对间隔
        LocalDate startDate1 = LocalDate.parse("2019-03-01", fmt);
        LocalDate endDate1 = LocalDate.parse("2020-07-08", fmt);
        System.out.println(String.format("总相差:%s年数,%s个月数,%s天数",
                startDate1.until(endDate1, ChronoUnit.YEARS),
                startDate1.until(endDate1, ChronoUnit.MONTHS),
                startDate1.until(endDate1, ChronoUnit.DAYS)));
        //常用日期获取
        // 本周一
        LocalDate with = LocalDate.now().with(DayOfWeek.of(1));
        // 下周一
        LocalDate with1 = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.of(1)));
        // 本月第一天
        LocalDate with2 = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        //下月第一天
        LocalDate with3 = LocalDate.now().plusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
        System.out.println(String.format("本周一:%s,下周一:%s,本月第一天:%s,下月第一天:%s", with, with1, with2, with3));
        /********************  String、Date、LocaDate、LocalTime、LocalDateTime 相互转换 ******************************/
        //String 与 Date相互转换
        // Date转String
        Date date = new Date();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        System.out.println(String.format("sdf1:%s,sdf2:%s,sdf3:%s", sdf1.format(date), sdf2.format(date), sdf3.format(date)));
        // String 转 Date
        String stringDate = "2016-10-24";
        String string = "2016-10-24 21:59:06";
        System.out.println(String.format("stringDate:%s", sdf2.parse(string)));
        //String 与 LocaDate相互转换
        // LocalDate 转 String
        System.out.println(String.format("LocalDate > string:%s", fmt.format(localDate)));
        //// String 转 LocalDate
        System.out.println(String.format("string > LocalDate:%s", LocalDate.parse(stringDate, fmt)));
        System.out.println(String.format("string > LocalDate:%s", LocalDate.parse("2017-09-28")));
        //如果用yyyy-MM-dd HH:mm:ss但是输出仍然只是年月日
        System.out.println(String.format("string > LocalDate:%s", LocalDate.parse("2017-09-28 11:11:11", dateTimeFormatter6)));
        // LocalTime 转 String
        DateTimeFormatter df = DateTimeFormatter.ofPattern("HH:mm:ss");
        System.out.println(String.format("LocaTime > string:%s", df.format(localTime)));
        //// String 转 LocalTime
        System.out.println(String.format("String > LocalTime:%s", LocalTime.parse("21:11:01", df)));
        // LocalTimeDate 转 String
        DateTimeFormatter df1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println(String.format("LocalTimeDate > String:%s", df1.format(localDateTime)));
        //String 转 LocalTimeDate
        System.out.println(String.format("String > LocalTimeDate:%s", LocalDateTime.parse("2017-09-28 23:11:11", df1)));
        /********************* Date 与 LocalDate相互转换 **********************/
        //LocalDate转Date
        ZoneId zoneId = ZoneId.systemDefault();
        Date from = Date.from(localDate.atStartOfDay().atZone(zoneId).toInstant());
        System.out.println(String.format("LocalDate > Date:%s", from));
        //Date转LocalDate
        System.out.println(String.format("Date > LocalDate:%s", new Date().toInstant().atZone(zoneId).toLocalDate()));
        //Date 与 LocalTime 转换
        System.out.println(String.format("Date > LocalTime:%s", new Date().toInstant().atZone(zoneId).toLocalDate()));
        /****************************************************/
        //Date 与 LocalDateTime相互转换
        // LocalDateTime转Date
        //在LocalDateTime 转 Date 时，需要使用到 Java 8的几个类
        //ZoneId/ZoneOffset：表示时区
        //ZonedDateTime： 表示特定时区的日期和时间
        //Instant：表示时刻，不直接对应年月日信息，需要通过时区转换
        //时区的日期和时间
        ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
        //获取时刻
        Date from1 = Date.from(zonedDateTime.toInstant());
        System.out.println(String.format("LocalDateTime > Date:%s", from1));
        // Date转LocalDateTime
        System.out.println(String.format("Date > LocalDateTime:%s", new Date().toInstant().atZone(zoneId).toLocalDateTime()));
        /**************************************************************/
        // LocalDateTime转LocalDate
        System.out.println(String.format("LocalDateTime > LocalDate:%s", localDateTime.toLocalDate()));
        // LocalDate转LocalDateTime
        System.out.println(String.format("LocalDate > LocalDateTime:%s,%s,%s", localDate.atStartOfDay(),
                localDate.atTime(8, 20, 33), localDate.atTime(LocalTime.now())));
        // LocalDateTime转LocalTime
        System.out.println(String.format("LocalDateTime > LocalTime:%s", localDateTime.toLocalTime()));
        // LocalDateTime 转 Long(毫秒时间戳)
        ZoneId zone = ZoneId.systemDefault();
        Instant instant2 = LocalDateTime.now().atZone(zone).toInstant();
        System.out.println(String.format("LocalDateTime > Long:%s", instant2.toEpochMilli()));
        // Long(毫秒时间戳) 转  LocalDateTime
        instant2 = Instant.ofEpochMilli(1640444137993L);
        System.out.println(String.format("Long > LocalDateTime:%s", LocalDateTime.ofInstant(instant2, zone)));
    }
}
